package com.guiji.text2video.job.task;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.guiji.text2video.common.core.utils.DateUtils;
import com.guiji.text2video.job.domain.NewsSimplePushVO;
import com.guiji.text2video.job.domain.SpiderNewsStat;
import com.guiji.text2video.job.domain.Text2videoConfig;
import com.guiji.text2video.job.domain.Text2videoJob;
import com.guiji.text2video.job.mapper.SpiderNewsStatMapper;
import com.guiji.text2video.job.mapper.Text2videoConfigMapper;
import com.guiji.text2video.job.mapper.Text2videoJobMapper;
import com.guiji.text2video.job.util.DingUtil;
import com.hankcs.hanlp.HanLP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * @Copyright (C), 2018-2021
 * @FileName: PushTask
 * @Author: scl
 * @Date: 2021/8/30 16:46
 * @Description: 配置公共推送逻辑
 */
@Component("pushTask")
public class PushTask {

    private static final Logger logger = LoggerFactory.getLogger(PushTask.class);

    //@Value("${file-cache.task-video-dir}")
    private String taskVideoPath = "/data/aiopen/text2video/taskVideos/";

    @Autowired(required = false)
    SpiderNewsStatMapper spiderNewsStatMapper;

    @Autowired(required = false)
    Text2videoJobMapper jobMapper;

    @Autowired(required = false)
    Text2videoConfigMapper configMapper;

    public void getTop5(List<Text2videoJob> listJobs, String channel, String username, String port) {
        if (listJobs.size() == 0) {
            return;
        }
        //截取前5个
        if (listJobs.size() > 5) {
            listJobs = listJobs.subList(0, 5);
        }
        for (Text2videoJob videoJob : listJobs) {
            //推送一个历史视频
            String path = "/home/centos/news_video/" + videoJob.getJobId() + ".mp4";
            NewsSimplePushVO NewsSimplePushVO = new NewsSimplePushVO();
            String title = videoJob.getTitle();
            if (title.length() > 100) {
                title = title.substring(0, 99);
            }
            NewsSimplePushVO.setTitle(title);
            NewsSimplePushVO.setPath(path);
            NewsSimplePushVO.setChannel(channel);
            NewsSimplePushVO.setUsername(username);
            String content = videoJob.getContent().replace("$$$", "");
            if (content.length() > 5000) {
                content = content.substring(0, 4999);
            }
            //文本摘要
            if (videoJob.getBackupText().contains("HotNews-Collection")) {
                NewsSimplePushVO.setDescription(content);
            } else {
                String newContent = "";
                List<String> list = HanLP.extractSummary(content, getSummarySize(content));
                for (String str : list) {
                    newContent = newContent + " " + str;
                }
                NewsSimplePushVO.setDescription(newContent);
            }

            //本地保存的路径
            String videoPath = taskVideoPath;
            if (videoJob.getBackupText().contains("HotNews-Collection")) {
                videoPath = videoPath.replace("taskVideos", "longVideos");
            } else {
                videoPath = videoPath.replace("taskVideos", "news");
            }


            String saveFile = videoPath + videoJob.getJobId() + ".mp4";
            long fileSizeBytes = new File(saveFile).length();

            String scpCmd = "scp -i /data/text2video/duix.pem  " + saveFile + " centos@44.236.176.10:/home/centos/news_video";

            String result = RuntimeUtil.execForStr(scpCmd);

            int count = 0;
            while (true) {
                if (count > 5) {
                    logger.info("scp命令失败停顿10秒,重试：6,终止方法，依然失败：{}", scpCmd);
                    return;
                }
                if (null == result || result.contains("No such file or directory")) {
                    break;
                }
                count++;
                logger.info("result:{}", result);
                logger.info("scp命令失败停顿10秒,重试：{},命令：{}", count, scpCmd);
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                result = RuntimeUtil.execForStr(scpCmd);
            }


            HttpResponse httpResponse = null;
            String url = "http://44.236.176.10" + port;
            //计算当前视频上传超时时间
            NewsSimplePushVO.setTimeout(getTimeoutSecond(fileSizeBytes));

            int timeTo = (getTimeoutSecond(fileSizeBytes) + 900) * 1000;

            try {
                httpResponse = HttpRequest.post(url).timeout(timeTo).body(JSONUtil.parseObj(NewsSimplePushVO).toString()).executeAsync();
            } catch (Exception e) {
                InsertStatSpider(videoJob, 1, null);
                FileUtil.del(saveFile);
                jobMapper.deleteText2videoJobById(videoJob.getJobId());
                logger.info("getTop5方法http请求异常:{},请求body:{}", e.toString(), JSONUtil.parseObj(NewsSimplePushVO).toString());
                return;
            }

            /**
             * @descp: ["is not clickable","Reached error page","Failed to decode response from marionette","element is no longer attached",
             * "TimedPromise timed out
             * "]
             * ["Reached error page","Failed to decode response from marionette",
             * "element is no longer attached","TimedPromise timed out
             * ","NoneType"]
             * 'YouTubeUploader' object has no attribute 'browser'
             * @param: 答应异常
             * @Author: scl
             * @Date: 2021/8/30 13:35
             * 'NoneType' object has no attribute 'click'
             *     "error": "Message: File not found: /home/centos/news_video/Job-20210917-104815-949492638.mp4\n"
             */
            boolean isDeleteVideo = httpResponse.body().contains("is not clickable")
                    || httpResponse.body().contains("Reached error page")
                    || httpResponse.body().contains("Failed to decode response from marionette")
                    || httpResponse.body().contains("element is no longer attached")
                    || httpResponse.body().contains("TimedPromise timed out")
                    || httpResponse.body().contains("Reached error page")
                    || httpResponse.body().contains("Failed to decode response from marionette")
                    || httpResponse.body().contains("element is no longer attached")
                    || httpResponse.body().contains("TimedPromise timed out");

            if (ObjectUtil.isNotEmpty(httpResponse) && httpResponse.getStatus() == 200) {
                logger.info("推送成功,频道:{},username:{},jobId:{},标题:{}", channel, username, videoJob.getJobId(), videoJob.getTitle());
                FileUtil.del(saveFile);
                jobMapper.deleteText2videoJobById(videoJob.getJobId());
                InsertStatSpider(videoJob, 0, httpResponse);
            } else {
                /**
                 * @descp: 500状态需要当前视频需要尝试。
                 * 501状态需要当前视频在草稿箱，不需要尝试推送。
                 * 502状态当前账号cookie过期。
                 * 503状态并发上限。
                 * 504状态已达到每日上传数上限。
                 * 505状态验证是否本人操作。
                 * @param: getTop10
                 * @Author: scl
                 * @Date: 2021/11/19 14:10
                 */
                if (ObjectUtil.isNotEmpty(httpResponse) && httpResponse.getStatus() == 505) {
                    InsertStatSpider(videoJob, 1, httpResponse);
                    logger.info("505状态验证本人操作:{}", fromCookieToUsename(NewsSimplePushVO.getUsername()));
                    DingUtil.sendMsg("!!! 监控到当前youtube账号验证本人操作", fromCookieToUsename(NewsSimplePushVO.getUsername()));
                    return;
                } else if (ObjectUtil.isNotEmpty(httpResponse) && httpResponse.getStatus() == 504) {
                    InsertStatSpider(videoJob, 1, httpResponse);
                    logger.info("504状态已达到每日上传数上限:{},保留视频:{}", NewsSimplePushVO.getUsername(), JSONUtil.parseObj(NewsSimplePushVO).toString());
                    return;
                } else if (ObjectUtil.isNotEmpty(httpResponse) && httpResponse.getStatus() == 503) {
                    InsertStatSpider(videoJob, 1, httpResponse);
                    logger.info("503状态并发上限，保留视频:{}", JSONUtil.parseObj(NewsSimplePushVO).toString());
                    return;
                } else if (ObjectUtil.isNotEmpty(httpResponse) && httpResponse.getStatus() == 502) {
                    InsertStatSpider(videoJob, 1, httpResponse);
                    logger.info("502状态当前账号cookie过期:{}", fromCookieToUsename(NewsSimplePushVO.getUsername()));
                    //告警钉钉
                    DingUtil.sendMsg("!!! 监控到当前youtube账号cookie过期", fromCookieToUsename(NewsSimplePushVO.getUsername()));
                    return;
                } else if (ObjectUtil.isNotEmpty(httpResponse) && httpResponse.getStatus() == 501) {
                    //表示视频投放成功
                    InsertStatSpider(videoJob, 1, httpResponse);
                    logger.info("501状态当前视频在草稿箱，不需要尝试推送");
                    FileUtil.del(saveFile);
                    jobMapper.deleteText2videoJobById(videoJob.getJobId());
                } else {
                    InsertStatSpider(videoJob, 1, httpResponse);
                    if (isDeleteVideo) {
                        logger.info("500错误不删除的错误：{}", JSONUtil.parseObj(NewsSimplePushVO).toString());
                        return;
                    } else {
                        FileUtil.del(saveFile);
                        jobMapper.deleteText2videoJobById(videoJob.getJobId());
                        logger.info("500错误需要删除，频道:{},使用jobId:{},视屏标题:{}", channel, videoJob.getJobId(), videoJob.getTitle());

                    }
                }
            }
        }
    }

    private int getSummarySize(String content) {
        if (content.length() > 4000) {
            return 12;
        } else if (content.length() > 3000) {
            return 10;
        } else if (content.length() > 2000) {
            return 8;
        } else if (content.length() > 1000) {
            return 6;
        } else {
            return 6;
        }
    }

    private String fromCookieToUsename(String cookie) {
        Text2videoConfig config = new Text2videoConfig();
        config.setBackup2(cookie);
        List<Text2videoConfig> list = configMapper.selectText2videoConfigList(config);
        if (list.size() >= 1) {
            return list.get(0).getBackup1();
        } else {
            return cookie;
        }
    }

    public void InsertStatSpider(Text2videoJob videoJob, int isError, HttpResponse httpResponse) {
        SpiderNewsStat spiderNewsStat = new SpiderNewsStat();
        spiderNewsStat.setNewsCategory(videoJob.getBackupText());
        //1表示推送状态
        spiderNewsStat.setStatSign(1);

        if (1 == isError) {
            spiderNewsStat.setNewsError(1);
            if (null == httpResponse) {
                spiderNewsStat.setBackup1("getTop5方法http请求异常!");
            } else {
                spiderNewsStat.setBackup1(httpResponse.body());
            }

            spiderNewsStat.setBackup2(videoJob.getTitle());

        } else {
            spiderNewsStat.setNewsCount(1);
            spiderNewsStat.setBackup1(videoJob.getJobId());
            spiderNewsStat.setBackup2(videoJob.getTitle());
        }
        spiderNewsStat.setCreateTime(DateUtils.getNowDate());
        spiderNewsStatMapper.insertSpiderNewsStat(spiderNewsStat);

    }


    public List<SpiderNewsStat> getSpiderNewsStat(SpiderNewsStat stat) {
        return spiderNewsStatMapper.selectSpiderNewsStatList(stat);
    }


    public int getTimeoutSecond(long fileSize) {
        if (ObjectUtil.isEmpty(fileSize)) {
            logger.info("获取文件大小失败，当前文件不存在");
            return 0;
        }

        int mBytes = (int) fileSize / 1024 / 1024;

        if (mBytes < 30) {
            //15分钟
            return 15 * 60;
        } else if (mBytes < 100) {
            //15分钟-50分钟
            return mBytes * 30;
        } else if (mBytes < 500) {
            //50分钟-83分钟
            return mBytes * 20;
        }
        //500M以上，一律120分钟
        return 120 * 60;
    }
}